package metamodel;

import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.beans.PropertyDescriptor;
import java.beans.IntrospectionException;

/**
 * User: felix
 * Date: 30.05.2005
 * Time: 21:27:46
 */
public abstract class Property {
    protected Property() {
    }

    public void setName(String name) {
        this.name = name;
    }

    private String name;
    protected PropertyDescriptor descriptor;
    ClassNode enclosing;

    public ClassNode getEnclosing() {
        return enclosing;
    }

    public void setEnclosing(ClassNode enclosing) {
        this.enclosing = enclosing;
    }


    Method getGetter() {
        return getDescriptor().getReadMethod();
    }
    Method getSetter() {
        return getDescriptor().getWriteMethod();
    }

    public Property(String name){
        this.name=name;
    }

    public String getName() {
        return name;
    }

    public Object getValue(Object o){
        try {
            return getGetter().invoke(o,new Object[0]);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

    public void setValue(Object o, Object value){
        try {

            getSetter().invoke(o,new Object[]{value});
        } catch (IllegalAccessException e) {
        } catch (NullPointerException npe){
            System.out.println("fuck");
        } catch (InvocationTargetException e) {

            throw new RuntimeException(e);
        }
    }

    public abstract String getTypeName();

    public Class getPropertyClass(){
        try {
            return getClass().getClassLoader().loadClass(getTypeName());
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
    public PropertyDescriptor getDescriptor() {
        if (descriptor==null){
            try {
                descriptor=new PropertyDescriptor(getName(),enclosing.getType());
            } catch (IntrospectionException e) {
                throw new RuntimeException(e);
            }
        }

        return descriptor;
    }

    public String toString() {
        return "property "+name;
    }
}
